package com.beney.app.context;

import com.beney.common.Identity;
import com.beney.common.SystemIn;
import com.beney.util.Commands;

/**
 * 登录后的监听状态
 *
 * @author Beney
 */
public class ListeningState extends AbstractState {
    protected ListeningState(AppContext context) {
        super(context);
    }

    @Override
    void runState()
    {
        System.out.print(Commands.wrapHintInputCommand(
                userService.getName(),
                userService.getIdentity(),
                "准备生成",
                userService.getIdentity(),
                "数学题目，请输入生成题目数量："
        ));
        loop: for (;;)
        {
            String input = SystemIn.CIN.nextLine().trim();
            int res = analyzeInput(input);
            switch (res)
            {
                case USER_EXIT:
                    context.shiftState(context.loginState, userService);
                    break loop;
                case NUM_ERR:
                    System.out.print(Commands.wrapHintInputCommand(
                            userService.getName(),
                            userService.getIdentity(),
                            "ERR: 题目数量非法，请输入10~30"));
                    break;
                case IDENTITY_ERR:
                    System.out.print(Commands.wrapHintInputCommand(
                            userService.getName(),
                            userService.getIdentity(),
                            "ERR: 请输入小学、初中和高中三个选项中的一个",
                            ", 例如'切换为高中'"
                    ));
                    break;
                case IDENTITY_SUC:

                    break loop;
                case OTHER_ERR:
                    System.out.print(Commands.wrapHintInputCommand(
                            userService.getName(),
                            userService.getIdentity(),
                            "ERR:非法输入!",
                            "请输入10~30的数字生成题目 或 切换身份'切换为XX'"
                    ));
                    break;
                default:
                    userService.generateQues(res);
                    break loop;
            }
        }
    }

    /**
     * 命令分析结果
     */
    private final int USER_EXIT = -1,
            NUM_ERR = 0,
            IDENTITY_ERR = 1,
            IDENTITY_SUC = 2,
            OTHER_ERR = 3;


    /**
     * 分析用户的输入值
     * 大致有三种情况：
     * 1. -1：直接退出当前账户；
     * 2. 全数字：判断是否是10~30之间；
     * 3. 非全数字：判断是否是切换身份的命令
     *
     * @param input 输入的字符串
     * @return 10~30 生成的题目数；
     *          USER_EXIT(-1) 退出当前账户；
     *          NUM_ERR(0) 题目数量切换非法；
     *          IDENTITY_ERR(1) 切换身份非法；
     *          IDENTITY_SUC(2) 切换身份成功；
     *          OTHER_ERR(3) 其他非法输出；
     */
    private int analyzeInput(String input)
    {
        int res, len;
        String identity;
        if (input == null)
            return OTHER_ERR;
        else if (input.equals("-1"))
            return USER_EXIT;
        else if (allIsNum(input)) {
            return (res = getNum(input)) == NUM_ERR ?
                    NUM_ERR : res;
        }
        else {
            if ((len = input.length()) >= Commands.ID_COMMAND_LEN + 2
                    && input.substring(0, Commands.ID_COMMAND_LEN).equals(Commands.ID_COMMAND))
            {
                if (len == Commands.ID_COMMAND_LEN + 2 && Identity.IsLegalIdentity(identity = input.substring(
                        Commands.ID_COMMAND_LEN,
                        Commands.ID_COMMAND_LEN+2)
                ))
                {
                    userService.setIdentity(identity); // 调用服务切换用户
                    return IDENTITY_SUC;
                }
                return IDENTITY_ERR;
            }
            return OTHER_ERR;
        }
    }

    private boolean allIsNum(String input) {
        for (char c : input.toCharArray()) {
            if (c < '0' || c >'9') return false;
        }
        return true;
    }

    /**
     * 数值范围在10~30才返回正确数值
     *
     * @param input 数字字符串
     * @return 10~30 或者 NUM_ERR
     */
    private int getNum(String input) {
        if (input.length() != 2)
            return NUM_ERR;
        int res = (input.charAt(0) - '0') * 10 + input.charAt(1) - '0';
        if (res >= 10 && res <= 30)
            return res;
        return NUM_ERR;
    }
}
